/**
 * vue专属
 */
import Stat from 'stat/core'

export default {
	install(vm) {
		const {
			report,
			chainLength,
			oncePageView,
			onceNodeView,
		} = this.options

		const stat = new Stat(report, { 
			chainLength,
			oncePageView,
			onceNodeView,
			startCallback: callback => this.data.startCallback = callback
		})

		vm.prototype.$Stat = stat // Stat实例
		vm.prototype.$clickStat = (arg, opt) => stat.clickReport(arg, opt) // 点击上报
		vm.prototype.$viewStat = (arg, opt) => stat.viewReport(arg, opt) // 页面上报
		vm.prototype.$stat = (arg, opt) => stat.nodeReport(arg, opt) // 节点上报
		vm.prototype.$handStat = (el, value) => stat.bindDom(el, value) // 手动绑定
		vm.prototype.$removeHandStat = (el, value) => stat.removeBind(el, value) // 手动移除绑定

		// 绑定
		const _bindDom = ( 
			el, 
			{ 
				value: { 
					id = '', 
					unBind = false, 
					unClick = false, 
					...params,
				} = {},
				oldValue,
			} = {},
		) => {
			if (!id || unBind) return
			if (oldValue) {
				// 解除引用
				const { id, unBind, unClick, ..._oldValue } = oldValue

				if (JSON.stringify(_oldValue) === JSON.stringify(params)) return
			}

			// 已有数据的指令执行速度优先于 _route.afterEach ，在这做判断
			const key = stat._currentKey !== stat._options.DOM_toKey ? stat._options.DOM_toKey : null

			return stat.bindDom(el, { id, unBind, unClick, ...params }, key)
		}

		// 移除绑定
		const _removeDom = ( 
			el, 
			{ 
				value: { 
					id = '', 
					unBind = false,
					unClick = false, 
				} = {}, 
			} = {}, 
		) => {
			if (!id || unBind) return
			
			return stat.removeBind(el, { id, unBind, unClick })
		}

		// 绑定指令
		vm.directive('stat', {
			inserted: _bindDom,
			componentUpdated: _bindDom,
			unbind: _removeDom,
		})

		// 提供额外页面栈参数
		stat.options.otherDataDefault = {
			pageStackMetaData: () => stat._route.getOwnPageStackParams('pageStackParams'),
			pageChainMetaData: () => stat._route.getOwnPageChainParams('pageChainParams'),
		}
		// 额外参数执行
		// stat.options.runKey = Object.keys(stat.options.otherDataDefault) // ['pageStackMetaData']

		// 监听路由
		if (this.options.unRouter) {
			// 不使用路由，使用自带路由
			stat.options.baseDataDefault.page = stat._route.options.pageStackParams.statName = stat._route.options.pageChainParams.statName = this.options.statName

			if (typeof this.data.startCallback === 'function') {
				this.data.startCallback()
				this.data.startCallback = null
			}
		} else {
			this.startRouter(stat)
		}

		this.data.installed = true
		this.data.stat = stat
	},
	startRouter(stat = this.data.stat) {
		typeof this.data.route === 'function' && this.data.route()

		let parentParams = {}
		let fromName = '/'
		let DOM_fromKey = '/'
		const { router } = this.options
		this.data.route = router && (stat.options.stopRouteReport = true) && router.afterEach((to, from) => {
			const { 
				metaPageName, 
				metaPageParamsGet, 
				from: _from, 
				stopVueRouteReport 
			} = this.options

			// beforeRouteEnter 传递的页面参数
			const metaStat = to.meta.statParams || to.meta._stat || {}
			// 向 watch-route 的 pageStack 传入相应参数
			const h5 = _from === 'client' ? 'H5-' : ''

			const toName = stat._route.options.pageStackParams.statName = stat._route.options.pageChainParams.statName =
				metaStat.pageName || 
				metaStat.page || 
				to.meta[metaPageName] || 
				to.meta.statName || 
				`${h5}${to.meta.name || to.path}`

			const params = 
				metaStat.pageParams || 
				(typeof to.meta[metaPageParamsGet] === 'function' ? to.meta[metaPageParamsGet](to, from) || false : false) ||
				Object.assign({}, to.params, to.query)

			// 修改节点存储的key，因vue存在渠道问题，基础的取值永远是渠道号 如： /shandianhezi /shandianhezi
			const DOM_toKey = to.path.match(/^\/[^/]*/)[0]
			stat._options.DOM_toKey = DOM_toKey
			stat._options.DOM_fromKey = DOM_fromKey
			
			// 修改默认参数
			stat.options.baseDataDefault = {
				page: toName,
				parentPage: fromName,
				parentParams,
				pageParams: params,
				actionParams: metaStat.actionParams || {},
			}

			// 下一次使用
			fromName = toName
			DOM_fromKey = DOM_toKey
			parentParams = params

			// 修改上报的默认 pathname
			stat.options.reportPathname = to.fullPath

			// 只执行一次 startCallback
			if (typeof this.data.startCallback === 'function') {
				this.data.startCallback()
				this.data.startCallback = null
			}

			// 当前页面阻止了默认的页面上报操作
			if (to.meta._autoStat === false) return

			// 阻止页面跳转上报
			if (stopVueRouteReport) return

			// 页面跳转上报
			setTimeout(() => stat.viewReport(), 4);
		})
	},

	/**
	 * @method set
	 * @description 设置值
	 * @param {String | Object} key 当key为String时，作为对象的key，当为对象时，直接进行合并
	 * @param {any} value 值 
	 */
	set(key, value) {
		if (!this.options.router && (key === 'router' || key.router) && this.data.installed) Promise.resolve().then(() => this.startRouter()) 

		if (typeof key === 'object') return Object.assign(this.options, key)

		return this.options[key] = value
	},
	options: {
		// 来自哪里使用，如：client
		from: '',
		// router实例，必传
		router: null,
		// 不使用router
		unRouter: false,
		// 不使用router时的页面栈名称
		statName: document.title,
		// 上报方法
		report: null,

		// 配置参数
		metaPageName: '',
		// 获取格式化 pageParams 数据的方法名，传入 route
        metaPageParamsGet: '',
		chainLength: 6,
		oncePageView: true,
		onceNodeView: true,
		// 停止 vue 页面自动上报
		stopVueRouteReport: false,
	},
	data: {
		// 销毁router
		route: null,
		// 安装完成
		installed: false,
		// stat实例
		stat: null,
		// 准备完成时，执行 watch-route 第一次添加
		// 若未传入router实例，则需手动执行一次
		startCallback: null,
	}
}